#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <vector>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "LexerModule.h"
#include "Catalogue.h"

#ifdef SCI_NAMESPACE
#error mmmmmmmmmmm
using namespace Scintilla;
#endif

#define LINK_LEXER(lexer) extern LexerModule lexer; Catalogue::AddLexerModule(&lexer);

static std::vector<LexerModule *> lexerCatalogue;
static int nextLanguage = SCLEX_AUTOMATIC + 1;

const LexerModule *Catalogue::Find( int language ) {
  Scintilla_LinkLexers();
  for( std::vector<LexerModule *>::iterator it = lexerCatalogue.begin();
       it != lexerCatalogue.end(); ++it ) {
    if( ( *it )->GetLanguage() == language ) {
      return *it;
    }
  }
  return 0;
}

const LexerModule *Catalogue::Find( const char *languageName ) {
  Scintilla_LinkLexers();
  if( languageName ) {
    for( std::vector<LexerModule *>::iterator it = lexerCatalogue.begin();
         it != lexerCatalogue.end(); ++it ) {
      if( ( *it )->languageName && ( 0 == strcmp( ( *it )->languageName, languageName ) ) ) {
        return *it;
      }
    }
  }
  return 0;
}

void Catalogue::AddLexerModule( LexerModule *plm ) {
  if( plm->GetLanguage() == SCLEX_AUTOMATIC ) {
    plm->language = nextLanguage;
    nextLanguage++;
  }
  lexerCatalogue.push_back( plm );
}

int Scintilla_LinkLexers() {
  static int initialised = 0;
  if( initialised ) {
    return 0;
  }
  initialised = 1;
  LINK_LEXER( lmAs );
  LINK_LEXER( lmAsm );
  LINK_LEXER( lmBash );
  LINK_LEXER( lmCmake );
  LINK_LEXER( lmConf );
  LINK_LEXER( lmCPP );
  LINK_LEXER( lmCPPNoCase );
  LINK_LEXER( lmCss );
  LINK_LEXER( lmErrorList );
  LINK_LEXER( lmHTML );
  LINK_LEXER( lmIHex );
  LINK_LEXER( lmLua );
  LINK_LEXER( lmMake );
  LINK_LEXER( lmMySQL );
  LINK_LEXER( lmNull );
  LINK_LEXER( lmPHPSCRIPT );
  LINK_LEXER( lmProps );
  LINK_LEXER( lmSrec );
  LINK_LEXER( lmTEHex );
  LINK_LEXER( lmXML );
  return 1;
}
